#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <sys/epoll.h>
#include <error.h>

#define MAXLINE 8192
#define SERV_PORT 8000
#define OPEN_MAX 5000


int main(int argc,char* argv[])
{
    int i,listenfd,connfd,sockfd;
    int n,num = 0;
    ssize_t nreadfy,efd,res;
    char buf[MAXLINE],str[INET_ADDRSTRLEN];
    socklen_t chilen;
    struct sockaddr_in cliaddr,servaddr;
    struct epoll_event tep,en[OPEN_MAX];//tep : epoll_ctl parm  ep[] epoll_wait parm

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    int opt = 1024;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(char*)&opt,sizeof(int));

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
    listen(listenfd,20);

    efd = epoll_create(OPEN_MAX);
    if(efd == -1)
    {
        perror("epoll create error");
        exit(1);
    }

    tep.events = EPOLLIN;
    tep.data.fd = listenfd;
    res = epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep);

    if(res == -1){
        perror("fail to epoll_ctl\n");
        exit(1);
    }
    while(1){
        nreadfy = epoll_wait(efd,en,OPEN_MAX,-1);
        if(nreadfy == -1){
            perror("fail to epoll_wait\n");
            exit(1);
        }
        for(i = 0;i<nreadfy;i++){
            if(!(en[i].events&EPOLLIN)){
                continue;
            }
            if(en[i].data.fd == listenfd){
                chilen = sizeof(socklen_t);
                connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&chilen);

                printf("received from %s at PORT %d\n",inet_ntop
                (AF_INET,&cliaddr.sin_addr,str,sizeof(str)),
                sizeof(str),ntohs(cliaddr.sin_port));
                printf("cfd %d----client %d\n",connfd,++num);

                tep.events = EPOLLIN;
                tep.data.fd = connfd;
                res = epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep);
            }
            else
            {
                sockfd = en[i].data.fd;
                n = read(sockfd,buf,MAXLINE);
                if(n == 0){
                    res = epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);
                    close(sockfd);
                }
                else if(n < 0)
                {
                    perror("err");
                    exit(1);

                }
                else
                {
                    for(i = 0;i<n;i++){
                        buf[i] = toupper(buf[i]);

                    }
                    write(stdout,"send file",10);
                    write(sockfd,buf,n);
                }
            }
        }
    }
}